package com.hethongviet.vending;

import java.util.ArrayList;
import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.Display;
import android.view.WindowManager;

import com.hethongviet.vending.helper.CodeResult;
import com.hethongviet.vending.helper.call.ListenPhoneCallService;
import com.hethongviet.vending.helper.db.BoxSQLite;
import com.hethongviet.vending.helper.db.MachineSQLite;
import com.hethongviet.vending.helper.db.ProductSQLite;
import com.hethongviet.vending.model.Account;
import com.hethongviet.vending.model.Box;
import com.hethongviet.vending.model.BoxItem;
import com.hethongviet.vending.model.MachineInfo;
import com.hethongviet.vending.model.Product;

/**
 * The main application, should not initiate, using the singleton through
 * getInstance(). This contains all common data
 */
public class AppMain extends Application
{

	/** Use for the singleton pattern */
	private static AppMain _instanceApp = null;

	/** The application is being in StandByScreen or not? */
	private boolean _isStandbyScreen = true;

	/** The result code is used for the network or any connection */
	private CodeResult _codeResult = CodeResult.NONE;

	/** The list contains the content of all boxes */
	private List<BoxItem> _listBoxItems = null;

	/** The current account */
	private Account _accountCurrent = null;

	/** The current index on the {@link #_listBoxItems} */
	private int _currentBoxItemIndex = 0;

	/** Total times for logout (go to the StandByScreen) */
	private int _numberActivityFinishLogout = 0;

	public AppMain()
	{
		_instanceApp = this;
		_isStandbyScreen = true;
		_codeResult = CodeResult.NONE;

		_listBoxItems = new ArrayList<BoxItem>();

		_currentBoxItemIndex = 0;
		_numberActivityFinishLogout = 0;
	}

	public synchronized static AppMain getInstance()
	{
		if (_instanceApp == null)
		{
			_instanceApp = new AppMain();
		}
		return _instanceApp;
	}

	@Override
	public void onTerminate()
	{
		stopService(new Intent(this, ListenPhoneCallService.class));

		super.onTerminate();
	}

	/**
	 * Get the info of the machine
	 * 
	 * @return {@link MachineInfo}
	 */
	public MachineInfo getMachineInfo()
	{
		MachineSQLite machineSQLite = new MachineSQLite(_instanceApp);
		MachineInfo machineInfo = null;

		try
		{
			machineInfo = machineSQLite.getAll().get(0);
		} catch (Exception e)
		{
			e.printStackTrace();

			machineInfo = new MachineInfo("VM001", 40,
					System.currentTimeMillis(), 0, 15, 342142142.23423, 0,
					234242.23423, "0975075350", "", "0975075350", 1, 1,
					"0975075350", "1C:B0:94:6E:B8:93", "00:12:03:09:14:98",
					"http://localhost", 1234);
		}

		return machineInfo;
	}

	/**
	 * Get the product with its code
	 * 
	 * @param listProducts
	 * @param productCode
	 * @return a {@link Product} or <B>null</B> if no {@link Product} valid
	 */
	private Product getProduct(List<Product> listProducts, String productCode)
	{
		if (listProducts != null)
		{
			for (Product product : listProducts)
			{
				if (product.getCode().equals(productCode))
					return product;
			}
		}
		return null;
	}

	/**
	 * Update the {@link BoxItem} list: {@link #_listBoxItems}
	 */
	public void updateListBoxItems()
	{
		/* Get all boxes */
		BoxSQLite boxSqLite = new BoxSQLite(_instanceApp);
		List<Box> boxsList = boxSqLite.getAll();

		/* Get all products */
		ProductSQLite productSqLite = new ProductSQLite(_instanceApp);
		List<Product> productsList = productSqLite.getAll();

		/* Get product available */
		if (_listBoxItems == null)
		{
			_listBoxItems = new ArrayList<BoxItem>();
		}
		else
		{
			_listBoxItems.clear();
		}

		for (Box box : boxsList)
		{
			BoxItem boxItem = new BoxItem();
			boxItem.setBox(box);

			String productCode = box.getProductCode();
			if (TextUtils.isEmpty(productCode))
			{
				boxItem.setProduct(null);
			}
			else
			{
				Product product = getProduct(productsList, productCode);
				if (product != null)
				{
					boxItem.setProduct(product);
				}
				else
				{
					boxItem.setProduct(null);
				}
			}
			_listBoxItems.add(boxItem);
		}
	}

	/**
	 * Update the current {@link BoxItem} list: {@link #_listBoxItems} with the
	 * box has the code
	 * 
	 * @param boxCode
	 *            the code of the box
	 */
	public void updateCurrentBox(int boxCode)
	{
		for (int index = 0; index < _listBoxItems.size(); index++)
		{
			if (_listBoxItems.get(index).getBox().getId() == boxCode)
			{
				_currentBoxItemIndex = index;
				return;
			}
		}
	}

	/**
	 * Get the list of {@link BoxItem} which contains {@link Product}
	 * 
	 * @param context
	 * @return the list of {@link BoxItem} which contains {@link Product}
	 */
	public List<BoxItem> getProducts()
	{
		if (_listBoxItems == null || _listBoxItems.size() == 0)
		{
			updateListBoxItems();
		}

		List<BoxItem> boxItems = new ArrayList<BoxItem>();

		for (BoxItem boxItem : _listBoxItems)
		{
			if (boxItem.getBox().getProductAmount() > 0)
			{
				boxItems.add(boxItem);
			}
		}
		return boxItems;
	}

	/**
	 * Get the current {@link Box} in the {@link #_listBoxItems}
	 * 
	 * @return current {@link Box} <B> null </B> if
	 *         {@link IndexOutOfBoundsException} has caused
	 */
	public Box getCurrentBox()
	{
		if (_listBoxItems == null || _listBoxItems.size() == 0)
		{
			updateListBoxItems();
		}

		try
		{
			return _listBoxItems.get(_currentBoxItemIndex).getBox();
		} catch (IndexOutOfBoundsException e)
		{
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * Get the current {@link BoxItem} in the {@link #_listBoxItems}
	 * 
	 * @return current {@link BoxItem} <B> null </B> if
	 *         {@link IndexOutOfBoundsException} has caused
	 */
	public BoxItem getCurrentBoxItem()
	{
		if (_listBoxItems == null || _listBoxItems.size() == 0)
		{
			updateListBoxItems();
		}

		try
		{
			return _listBoxItems.get(_currentBoxItemIndex);
		} catch (IndexOutOfBoundsException e)
		{
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * Check the context is running or not?
	 * 
	 * @param packagePathContext
	 *            the path of the context following the package name
	 * @return <B>true</B> if the context is running <B>false</B> if otherwise
	 */
	public boolean isContextRunning(String packagePathContext)
	{

		ActivityManager activityManager = (ActivityManager) _instanceApp.getBaseContext().getSystemService(
				Context.ACTIVITY_SERVICE);

		List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE);

		for (RunningTaskInfo runningTaskInfo : services)
		{
			if (runningTaskInfo.topActivity.toString().contains(
					packagePathContext))
				return true;
		}
		return false;
	}

	public int getScreenWidth()
	{
		Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
		return display.getWidth();
	}

	public int getScreenHeight()
	{
		Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
		return display.getHeight();
	}

	public boolean isStandbyScreen()
	{
		return _isStandbyScreen;
	}

	public void setStandbyScreen(boolean _isStandbyScreen)
	{
		this._isStandbyScreen = _isStandbyScreen;
	}

	public CodeResult getCodeResult()
	{
		return _codeResult;
	}

	public void setCodeResult(CodeResult _codeResult)
	{
		this._codeResult = _codeResult;
	}

	public Account getCurrentAccount()
	{
		return _accountCurrent;
	}

	public void setCurrentAccount(Account _accountCurrent)
	{
		this._accountCurrent = _accountCurrent;
	}

	public int getNumberActivityFinishLogout()
	{
		return _numberActivityFinishLogout;
	}

	public void setNumberActivityFinishLogout(int _numberActivityFinishLogout)
	{
		this._numberActivityFinishLogout = _numberActivityFinishLogout;
	}

	public List<BoxItem> getListBoxItems()
	{
		return _listBoxItems;
	}

	public void setListBoxItems(List<BoxItem> _listBoxItems)
	{
		this._listBoxItems = _listBoxItems;
	}

	public int getCurrentBoxItemIndex()
	{
		return _currentBoxItemIndex;
	}

	public void setCurrentBoxItemIndex(int currentBoxItemIndex)
	{
		if (_listBoxItems == null || _listBoxItems.size() == 0)
		{
			updateListBoxItems();
		}

		if (currentBoxItemIndex >= 0
				&& currentBoxItemIndex < _listBoxItems.size())
		{
			_currentBoxItemIndex = currentBoxItemIndex;
		}
		else
		{
			_currentBoxItemIndex = 0;
		}
	}

}
